package com.ikingtech.platform.service.system.division.service;

import com.ikingtech.framework.sdk.context.event.SystemInitEvent;
import com.ikingtech.framework.sdk.enums.system.division.DivisionCategoryEnum;
import com.ikingtech.framework.sdk.enums.system.division.DivisionLevelEnum;
import com.ikingtech.framework.sdk.utils.Tools;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@Slf4j
@RequiredArgsConstructor
public class DivisionService {

    private final StringRedisTemplate redisTemplate;

    @EventListener(SystemInitEvent.class)
    public void systemInitEventListener() {
        if (Boolean.TRUE.equals(this.redisTemplate.hasKey(DivisionLevelEnum.PROVINCE.cacheKey()))) {
            return;
        }
        String csvFilePath;
        String divisionInfoTemplate = """
                {
                  "code": {},
                  "name": "{}",
                  "divisionLevel": "{}",
                  "parentCode": {},
                  "divisionCategory": "{}"
                }
                """;
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            String userProfile = System.getenv("USERPROFILE");
            csvFilePath = userProfile + "\\.iking\\area_code.csv";
        } else {
            csvFilePath = "/opt/iking/area_code.csv";
        }
        List<String> proviceList = new ArrayList<>();
        Map<Long, List<String>> cityMap = new HashMap<>();
        Map<Long, List<String>> districtMap = new HashMap<>();
        Map<Long, List<String>> townMap = new HashMap<>();
        Map<Long, List<String>> villageMap = new HashMap<>();
        Tools.Csv.readByLine(csvFilePath, csvLine -> {
            List<String> divisionInfo = Tools.Str.split(csvLine);
            Long parentCode = Long.parseLong(divisionInfo.get(3));
            Long code = Long.parseLong(divisionInfo.get(0));
            DivisionLevelEnum divisionLevel = DivisionLevelEnum.valueOf(Integer.parseInt(divisionInfo.get(2)));
            if (null == divisionLevel) {
                log.info("[N/A]行政区划CSV数据格式不正确 行政区划级别 -> {}", divisionInfo.get(2));
            } else {
                DivisionCategoryEnum divisionCategory = DivisionCategoryEnum.valueOf(Integer.parseInt(divisionInfo.get(4)));
                if (null == divisionCategory) {
                    log.info("[N/A]行政区划CSV数据格式不正确 行政区划类别 -> {}", divisionInfo.get(4));
                } else {
                    String divisionStr = Tools.Str.format(divisionInfoTemplate,
                            code,
                            divisionInfo.get(1),
                            divisionLevel.name(),
                            parentCode,
                            divisionCategory.name());
                    switch (divisionLevel) {
                        case PROVINCE:
                            proviceList.add(divisionStr);
                            break;
                        case CITY:
                            cityMap.computeIfAbsent(parentCode, k -> new ArrayList<>()).add(divisionStr);
                            break;
                        case DISTRICT:
                            districtMap.computeIfAbsent(parentCode, k -> new ArrayList<>()).add(divisionStr);
                            break;
                        case TOWN:
                            townMap.computeIfAbsent(parentCode, k -> new ArrayList<>()).add(divisionStr);
                            break;
                        case VILLAGE:
                            villageMap.computeIfAbsent(parentCode, k -> new ArrayList<>()).add(divisionStr);
                    }
                }
            }
        });
        if (Tools.Coll.isNotBlank(proviceList)) {
            this.redisTemplate.opsForList().leftPushAll(DivisionLevelEnum.PROVINCE.cacheKey(), proviceList);
        }
        if (Tools.Coll.isNotBlankMap(cityMap)) {
            cityMap.forEach((parentCode, divisionList) -> this.redisTemplate.opsForList().leftPushAll(DivisionLevelEnum.CITY.cacheKey(parentCode), divisionList));
        }
        if (Tools.Coll.isNotBlankMap(districtMap)) {
            districtMap.forEach((parentCode, divisionList) -> this.redisTemplate.opsForList().leftPushAll(DivisionLevelEnum.DISTRICT.cacheKey(parentCode), divisionList));
        }
        if (Tools.Coll.isNotBlankMap(townMap)) {
            townMap.forEach((parentCode, divisionList) -> this.redisTemplate.opsForList().leftPushAll(DivisionLevelEnum.TOWN.cacheKey(parentCode), divisionList));
        }
        if (Tools.Coll.isNotBlankMap(villageMap)) {
            villageMap.forEach((parentCode, divisionList) -> this.redisTemplate.opsForList().leftPushAll(DivisionLevelEnum.VILLAGE.cacheKey(parentCode), divisionList));
        }
    }
}
